package myou.control;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import myou.model.Acao;
import myou.model.Gerente;
import myou.model.Modulo;
import myou.util.LeitorConfiguracao;

/**
 * Projeto Myou - Disciplina: Sistemas de Informação I
 * Classe responsável controlar o fluxo de informações entre a Visão e o Modelo
 * @author Ronycley Gonçalves Agra
 * @version 1.00
 * @since Milestone 2 17/10/2011
 */
public class Controlador {
	
	private static Controlador instance;
	private LeitorConfiguracao config;
	
	protected Controlador() throws Exception{
		try{
			config = LeitorConfiguracao.getInstance();
		}catch(Exception e){
			throw e;
		}
	}
	
	/**
	 * @return LeitorConfiguracao O leitor de configuração do sistema
	 */
	public LeitorConfiguracao getLeitorConfiguracao(){
		return this.config;
	}
	
	
	/**
	 * Método que retorna uma instancia da classe (Singleton)
	 * @return Controlador Uma instancia de Controlador
	 * @throws Exception Lança exceção caso ocorre alguma problema na 
	 * ciração do objeto
	 */
	public synchronized static Controlador getInstance() throws Exception {
		try{
			if(instance == null){
				instance = new Controlador();
			}
			return instance;
		}catch(Exception e){
			throw e;
		}
	}

	/**
	 * @param ordemModulo
	 * @param ordemAcao
	 * @param valores
	 * @return Object O valor retornado pela ação
	 * @throws Exception
	 */
	public Object processar(String ordemModulo, String ordemAcao, Object[] valores) throws Exception{
		try{
			Modulo modulo = this.getLeitorConfiguracao().getModulo(ordemModulo);
			return this.executar(modulo.getGerente(),modulo.getAcao(ordemAcao), valores);
		}catch(Exception e){
			throw e;
		}
	}
	
	/**
	 * @param gerente 
	 * @param acao
	 * @param valores
	 * @return Object O retorno do método invocado
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public Object executar(Gerente gerente, Acao acao, Object[] valores) throws Exception {
		try{
			Class<Gerente> gerenteClass = (Class<Gerente>) gerente.getClass();
			String nomeMetodoGerente = acao.getMetodoGerente().getNome();
			Class tipoParametros[] = acao.getMetodoGerente().getTipoParametros();
	        Method metodoGerente = gerenteClass.getMethod(nomeMetodoGerente, tipoParametros); 
	        return metodoGerente.invoke(gerente, valores);
		}catch (IllegalAccessException e) {
			throw e;
		} catch (IllegalArgumentException e) {
			throw e;
		} catch (InvocationTargetException e) {
			throw e;
		}
	}
}
